#include "vulkanpainter.h"

#include <GPUBezierThickLineGenerator.h>
#include <QPainter>
#include <QDebug>

#include <log/Log.h>

#include <utils/TimeUtils.h>

VulkanPainter::VulkanPainter() {
    device = new QVulkanPaintDevice();

    device->setSize(drawSize);
}

QImage VulkanPainter::Paint(size_t line, size_t nums)
{
    QPainter painter;
    bool success = painter.begin(device);
    if (!success) {
        qFatal() << "QPainter::begin() failed!";
    } else {
        QBrush brush;
        brush.setStyle(Qt::BrushStyle::SolidPattern);

        BezierParams bezierParams{};
        bezierParams.lineNums = line;
        bezierParams.bodyPointsNums = nums;
        bezierParams.assPointsNums = 30;
        bezierParams.headPointsNums = 10;

        static GPUBezierThickLineGenerator utils;

        if (!initialized) {
            if (!utils.InitializeGPUPipeline(bezierParams)) {
                Logger() << "Failed to initialize GPU pipeline." << std::endl;
                exit(1);
            }
            initialized = true;
        }

        std::vector<BezierLine> lines{};
        for (uint32_t i = 0; i < bezierParams.lineNums; i++) {
            BezierLine line{
                            .points = {
                                       {.x = 100.0, .y = 100 + (1024.0f / bezierParams.lineNums) * static_cast<float>(i)},
                                       {.x = 300.0, .y = 20.0},
                                       {.x = 800.0, .y = 100.0},
                                       {.x = 800.0, .y = 700.0},
                                       },
                            .beginWidth = 100.0f,
                            .endWidth = 1.0f,
                            };
            lines.push_back(line);
        }

        const uint64_t now = TimeUtils::GetCurrentMonoMs();
        const Point2D *points = utils.GenerateThickLine(lines);
        const uint64_t last = TimeUtils::GetCurrentMonoMs();

        std::cout << "Totally Usage: " << last - now << " ms" << std::endl;
        const size_t pointsNums = bezierParams.bodyPointsNums + bezierParams.assPointsNums + bezierParams.headPointsNums;

        for (uint32_t lineIdx = 0; lineIdx < bezierParams.lineNums; lineIdx++) {
            brush.setColor(QColor(rand() % 255, rand() % 255, rand() % 255));
            QPainterPath path;
            for (uint32_t pointIdx = 0; pointIdx < pointsNums * 2; pointIdx++) {
                const uint32_t offset = lineIdx * pointsNums  * 2;
                const auto [x, y] = points[offset + pointIdx];
                if (pointIdx == 0) {
                    path.moveTo({x,y});
                } else {
                    path.lineTo({x,y});
                }
            }

            path.closeSubpath();
            painter.fillPath(path, brush);
        }

        painter.end();
    }


    return QImage();
}
